<?php

namespace services\buss;

use api\modules\common\services\UploadService;
use api\modules\v1\forms\buss\ToolForm;
use common\components\Service;
use common\helpers\CommonHelper;
use common\helpers\DateHelper;
use common\helpers\FileHelper;
use common\helpers\RedisHelper;
use common\models\base\Tags;
use common\models\base\ToolCategory;
use common\models\buss\CommonRelation;
use common\models\buss\Tool;
use common\models\buss\ToolFile;
use common\models\buss\ToolWater;
use common\models\member\Member;
use common\models\sys\SysFile;
use services\base\CommonRelationService;
use services\base\TagsService;
use services\base\ToolCategoryService;
use services\log\LogMemberOpService;
use services\member\MemberService;
use services\sys\SysFileService;
use Yii;

/**
 * Class ToolService
 * @package services\buss
 */
class ToolService extends Service
{
    /**
     * 工具列表
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = Tool::find()->alias('t')
            ->select([
                't.*',
//                'sf.origin_name', 'sf.origin_size',
            ]);
//            ->leftJoin(SysFile::tableName().' sf', 'sf.id = t.file_id');
        if (isset($params['project_ids']) && $params['project_ids']) {
            $params['project_ids'] = is_array($params['project_ids']) ? $params['project_ids'] : explode(',', $params['project_ids']);
            $query->andWhere(['t.project_id' => $params['project_ids']]);
        } else {
            $query->andWhere(['t.project_id' => array_column(MemberService::getProjectListCondition(), 'value')]);
        }
        if (isset($params['status']) && is_numeric($params['status'])) {
            $query->andWhere(['t.status' => $params['status']]);
        } else {
            $query->andWhere(['t.status' => [Tool::STATUS_INVALID, Tool::STATUS_ENABLE]]);
        }
//        if (isset($params['created_stime']) && $params['created_stime']) {
//            $query->andWhere(['>=', 't.created_at', strtotime($params['created_stime'])]);
//        }
//        if (isset($params['created_etime']) && $params['created_etime']) {
//            $query->andWhere(['<=', 't.created_at', strtotime($params['created_etime'].' 23:59:59')]);
//        }
        if (isset($params['tag_ids']) && $params['tag_ids']) {
            $params['tag_ids'] = is_array($params['tag_ids']) ? $params['tag_ids'] : explode(',', $params['tag_ids']);
            $query->andWhere(['t.id' => CommonRelationService::getTagToolIds($params['tag_ids'])]);
        }
        if (isset($params['keyword']) && $params['keyword']) {
            /*$query->andWhere([
                'or',
                ['like', 't.name', $params['keyword']],
                ['like', 't.desc', $params['keyword']],
                ['like', 'sf.origin_name', $params['keyword']],
            ]);*/
            $query->andWhere(['like', 't.name', $params['keyword']]);
        }
//        if (isset($params['created_member_id']) && $params['created_member_id']) {
//            $query->andWhere(['t.created_member_id' => $params['created_member_id']]);
//        }
        if (isset($params['age_ids']) && $params['age_ids']) {
            $params['age_ids'] = is_array($params['age_ids']) ? $params['age_ids'] : explode(',', $params['age_ids']);
            $query->andWhere(['t.age_id' => $params['age_ids']]);
        }
        if (isset($params['actegory_ids']) && $params['actegory_ids']) {
            $params['actegory_ids'] = is_array($params['actegory_ids']) ? $params['actegory_ids'] : explode(',', $params['actegory_ids']);
            $params['actegory_ids'] = array_values(array_filter(array_unique($params['actegory_ids'])));
            $query->andWhere(['t.id' => CommonRelationService::getEqualCategoryToolIds($params['actegory_ids'])]);
        }
        // 排序
        $order = [];
        if (isset($params['order_column']) && $params['order_column']) {
            $sort = isset($params['order_sort']) && $params['order_sort'] == 'asc' ? SORT_ASC : SORT_DESC;
            switch ($params['order_column']) {
                case 'download_total_num':
                case 'created_at':
                    $order["t.{$params['order_column']}"] = $sort;
                    break;
                default:
                    break;
            }
            $order && $order['t.id'] = SORT_DESC;
        }
        empty($order) && $order = ['t.status' => SORT_DESC, 't.id' => SORT_DESC];

        return $this->getListPageRes($query, $page, $pageSize, $order);
    }

    /**
     * 格式化列表
     * @param array $data
     * @return array
     */
    /*public function getListPageFormat(array $data = []): array
    {
        $list = [];
        foreach ($data as $row) {
            $tags = TagsService::getNormalListByIds(Tags::TYPE_TOOL, CommonRelationService::getToolTagIds($row['id']));

            $list[] = [
                'id' => $row['id'],
                'project_name' => RedisHelper::getProject($row['project_id'])->project_name ?? '',
                'name' => $row['name'],
                'url' => CommonHelper::getUrlFormat($row['url']),
                'desc' => $row['desc'],
                'file_name' => $row['origin_name'] ?: '',
//                'file_url' => $row['file'] ? UploadService::getFileDownloadUrl(SysFile::SITE_TOOL, SysFile::MODULE_TOOL, $row['file']) : '',
                'file_size' => $row['file_id'] ? CommonHelper::getFileSizeFormat($row['origin_size'] ?: 0) : '',
                'tag_arr' => array_column($tags, 'name'),
                'created_member_name' => RedisHelper::getMember($row['created_member_id'])->realname ?? '',
                'status_str' => Tool::$statuss[$row['status']] ?? '',
                'created_at_str' => DateHelper::timestampToDate($row['created_at'], DateHelper::DATE_FORMAT_1),
                'updated_at_str' => DateHelper::timestampToDate($row['updated_at'], DateHelper::DATE_FORMAT_1),
            ];
        }
        return $list;
    }*/
    public function getListPageFormat(array $data = []): array
    {
        // 工具图片、视频数
        $toolFileData = ToolFileService::getStaticsToolNum(array_column($data, 'id'));

        $list = [];
        foreach ($data as $row) {
            // 缩略图
            $thumbUrl = $row['thumb_image']
                ? UploadService::getFileTrueUrl(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_IMAGE, $row['thumb_image'], SysFile::STATUS_FORMAL, ['min' => 1])
                : ($row['thumb_video']
                    ? UploadService::getFileTrueUrl(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_VIDEO, $row['thumb_video'])
                    : '');
            $list[] = [
                'id' => $row['id'],
                'name' => $row['name'],
                'download_image_num' => $toolFileData[$row['id']][ToolFile::TYPE_IMAGE],
                'download_video_num' => $toolFileData[$row['id']][ToolFile::TYPE_VIDEO],
                'download_total_num' => $row['download_total_num'],
                'thumb_url' => $thumbUrl,
            ];
        }
        return $list;
    }

    /**
     * 获取工具创建人IDs
     * @return array
     */
    public static function getCreateMemberIds(): array
    {
        return Tool::find()
            ->select(['created_member_id'])
            ->andWhere(['status' => [Tool::STATUS_INVALID, Tool::STATUS_ENABLE]])
            ->column();
    }

    /**
     * 状态下拉筛选项
     * @return array[]
     */
    public static function getStatusCondition(): array
    {
        return [
            ['value' => Tool::STATUS_ENABLE, 'label' => Tool::$statuss[Tool::STATUS_ENABLE]],
            ['value' => Tool::STATUS_INVALID, 'label' => Tool::$statuss[Tool::STATUS_INVALID]],
        ];
    }

    /**
     * 操作人列表
     * @return array
     */
    public static function getCreatedMemberList(): array
    {
        $ids = self::getCreateMemberIds();
        return $ids ? MemberService::getListCondition($ids) : [];
    }

    /**
     * 列表筛选项
     * @return array
     */
    public function getSelectCondition(): array
    {
        return [
//            'status' => self::getStatusCondition(),
//            'created_member' => self::getCreatedMemberList(),
            'tag' => TagsService::getListCondition(Tags::TYPE_TOOL),
            'project' => MemberService::getProjectListCondition(),
        ];
    }

    /**
     * 工具详情
     * @param array $params
     * @return array
     */
    public function getInfo(int $id): array
    {
        // 工具信息
        $tool = Tool::findOne($id);
        if (empty($tool)) {
            return CommonHelper::api(422, '素材库不存在');
        }

        $file = $tool->file ? SysFileService::getSysFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file) : [];
        $tags = TagsService::getNormalListByIds(Tags::TYPE_TOOL, CommonRelationService::getToolTagIds($tool->id));
        $category = ToolCategoryService::getNormalListByIds(array_merge(CommonRelationService::getToolCategoryIds($tool->id), [$tool->age_id]));
        $fileArr = ToolFileService::getToolFileListFormat($tool->id);
        $imageNum = $videoNum = 0;
        foreach ($fileArr as $row) {
            if ($row['type'] == ToolFile::TYPE_IMAGE) {
                $imageNum++;
            } else {
                $videoNum++;
            }
        }
        // 水印设置
        $toolWaterData = ToolWaterService::getProjectWaterData($tool->project_id);
        $data = [
            'id' => $tool->id,
            'project_name' => RedisHelper::getProject($tool->project_id)->project_name ?? '',
            'name' => $tool->name,
            'desc' => $tool->desc,
            'file_name' => $file->origin_name ?? '',
            'tag_arr' => array_column($tags, 'name'),
            'category_arr' => array_column($category, 'name'),
            'file_arr' => $fileArr,
            'image_num' => $imageNum,
            'video_num' => $videoNum,
            'is_set_water' => $toolWaterData['type'] ? 1 : 0,
        ];
        return $data;
    }

    /**
     * 获取工具编辑详情
     * @param array $params
     * @return array
     */
    public function getEditInfo(int $id): array
    {
        $data = [
            'support_type' => UploadService::getSupportFileTypes(),
            'support_image_type' => UploadService::$imageTypeArr,
            'support_video_type' => UploadService::$videoTypeArr,
        ];
        // 工具信息
        $tool = Tool::findOne($id);
        if ($tool) {
            $file = $tool->file ? SysFileService::getSysFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file) : [];
            $categorys = ToolCategoryService::getNormalListByIds(CommonRelationService::getToolCategoryIds($tool->id));
            $data = array_merge($data, [
                'id' => $tool->id,
                'project_id' => $tool->project_id,
                'name' => $tool->name,
                'desc' => $tool->desc,
                'tag_ids' => array_column(TagsService::getNormalListByIds(Tags::TYPE_TOOL, CommonRelationService::getToolTagIds($tool->id)), 'id'),
                'file' => $tool->file,
                'file_name' => $file->origin_name ?? '',
                'file_url' => $tool->file ? UploadService::getFileTrueUrl(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file) : '',
                'image' => ToolFileService::getEditToolImage($tool->id),
                'video' => ToolFileService::getEditToolVideo($tool->id),
                'age_id' => $tool->age_id,
                'category_ids' => array_column($categorys, 'id'),
            ]);
            $categoryCondition = array_merge($data['category_ids'], array_column($categorys, 'pid'));
        }
        $condition = [
            'tag' => TagsService::getEditCondition(Tags::TYPE_TOOL,$data['tag_ids'] ?? null),
            'project' => MemberService::getProjectEditCondition($data['project_id'] ?? null),
            'category' => ToolCategoryService::getEditTree($categoryCondition ?? null),
            'age' => ToolCategoryService::getEditCondition($data['age_id'] ?? null, ToolCategory::ID_AGE),
        ];
        if ($tool) {
            $data['tag_ids'] = array_intersect($data['tag_ids'], array_column($condition['tag'], 'value'));
            if (in_array($data['project_id'], array_column($condition['project'], 'value')) === false) {
                $data['project_id'] = 0;
            }
            $allIds = [];
            foreach ($condition['category'] as $row) {
                $allIds[] = $row['value'];
                foreach ($row['children'] as $item) {
                    $allIds[] = $item['value'];
                }
            }
            $data['category_ids'] = array_intersect($data['category_ids'], $allIds);
            if (in_array($data['age_id'], array_column($condition['age'], 'value')) === false) {
                $data['age_id'] = 0;
            }
        }
        return array_merge($data, ['condition' => $condition]);
    }

    /**
     * 编辑工具
     * @param Tool $tool
     * @param ToolForm $model
     * @return Tool
     * @throws \Exception
     */
    public static function editModel(Tool $tool, ToolForm $model): Tool
    {
        $tool->project_id = $model->project_id;
        $tool->name = $model->name;
        $tool->desc = $model->desc ?: '';
        $file = $model->getFile();
        if (empty($model->file) || empty($file)) {
            $tool->file = '';
            $tool->file_id = 0;
        } else {
            $tool->file = $file->file;
            $tool->file_id = $file->id;
        }
        $tool->thumb_image = $model->image[0] ?? '';
        $tool->thumb_video = UploadService::getVoiceThumbImageName($model->video[0] ?? '');
        $tool->age_id = $model->age_id ?: 0;
        if ($model->getScenario() == 'create') {
            $tool->created_member_id = Yii::$app->user->identity->member_id;
        } else {
            $delNum = 0;
            if ($model->getDelImage()) {
                $oldToolImageList = array_column($model->getOldToolImageList(), null, 'file');
                foreach ($model->getDelImage() as $file) {
                    $delNum += $oldToolImageList[$file]->download_num;
                }
            }
            if ($model->getDelVideo()) {
                $oldToolVideoList = array_column($model->getOldToolVideoList(), null, 'file');
                foreach ($model->getDelVideo() as $file) {
                    $delNum += $oldToolVideoList[$file]->download_num;
                }
            }
            $tool->download_total_num -= $delNum;
        }
        $tool->status = Tool::STATUS_ENABLE;
        $tool->operation_id = Yii::$app->user->identity->member_id;
        $tool->operation_name = Yii::$app->user->identity->member->realname;
        $tool->saveAndCheckResult();

        return $tool;
    }

    /**
     * 新增工具
     * @param ToolForm $model
     * @return array
     */
    public function create(ToolForm $model): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1-1.新增工具
            $tool = new Tool();
            $tool = self::editModel($tool, $model);
            // 1-2.新增标签
            CommonRelationService::editModel(CommonRelation::TYPE_TOOL_TAG, $tool->id, $model->getAddTagIds());
            // 1-3.新增分类
            CommonRelationService::editModel(CommonRelation::TYPE_TOOL_CATEGORY, $tool->id, $model->getAddCategoryIds());
            // 1-4.更新图片
            ToolFileService::editModel($tool->id, ToolFile::TYPE_IMAGE, $model->getAddImage());
            // 1-5.更新视频
            ToolFileService::editModel($tool->id, ToolFile::TYPE_VIDEO, $model->getAddVideo());
            // 2-1.更新附件信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file);
            // 2-2.更新图片信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_IMAGE, $model->getAddImage());
            // 2-3.更新视频信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_VIDEO, $model->getAddVideo());
            // 3.日志
            LogMemberOpService::createToolLog($model, $tool);

            $transaction->commit();
            return ['id' => $tool->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 编辑工具
     * @param ToolForm $model
     * @return array
     */
    public function edit(ToolForm $model): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1-1.更新工具
            $oldTool = new Tool();
            $oldTool->setAttributes($model->getTool()->getAttributes());
            $tool = self::editModel($model->getTool(), $model);
            // 1-2.新增标签
            CommonRelationService::editModel(CommonRelation::TYPE_TOOL_TAG, $tool->id, $model->getAddTagIds(), $model->getDelTagIds());
            // 1-3.新增分类
            CommonRelationService::editModel(CommonRelation::TYPE_TOOL_CATEGORY, $tool->id, $model->getAddCategoryIds(), $model->getDelCategoryIds());
            // 1-4.更新图片
            ToolFileService::editModel($tool->id, ToolFile::TYPE_IMAGE, $model->getAddImage(), $model->getDelImage());
            // 1-5.更新视频
            ToolFileService::editModel($tool->id, ToolFile::TYPE_VIDEO, $model->getAddVideo(), $model->getDelVideo());
            // 2-1.更新附件信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file, $oldTool->file);
            // 2-2.更新图片信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_IMAGE, $model->getAddImage(), $model->getDelImage());
            // 2-3.更新视频信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_VIDEO, $model->getAddVideo(), $model->getDelVideo());
            // 3.日志
            LogMemberOpService::createToolLog($model, $tool, $oldTool);

            $transaction->commit();
            return ['id' => $tool->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 删除工具
     * @param ToolForm $model
     * @return array
     */
    public function delete(ToolForm $model): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.更新工具
            $tool = $model->getTool();
            $tool->status = Tool::STATUS_DELETE;
            $tool->operation_id = Yii::$app->user->identity->member_id;
            $tool->operation_name = Yii::$app->user->identity->member->realname;
            $tool->saveAndCheckResult();
            // 2-1.更新附件信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, '', $tool->file);
            // 2-2.更新图片信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_IMAGE, '', array_column($model->getOldToolImageList(), 'file'));
            // 2-3.更新视频信息
            SysFileService::editFile(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_VIDEO, '', array_column($model->getOldToolVideoList(), 'file'));
            // 3.日志
            LogMemberOpService::createToolLog($model, $tool);

            $transaction->commit();
            return ['id' => $tool->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 下载内容
     * @param array $params
     * @return array
     */
    public function download(ToolForm $model, int $isDownloadWater): array
    {
        // 内容信息
        $tool = $model->getTool();
        if (in_array($tool->project_id, array_column($model->getHaveProjectList(), 'value')) === false) {
            return CommonHelper::api(422, '未绑定该项目，无权限下载');
        }

        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.更新下载次数
            if ($model->download_type == 'attachment') {
                $tool->download_num += 1;
                $tool->download_total_num += 1;
                $tool->saveAndCheckResult();
            } else {
                $downloadTotalNum = 0;
                foreach ($model->getDownloadToolFileList() as $toolFile) {
                    $toolFile->download_num += 1;
                    $toolFile->saveAndCheckResult();
                    // 统计总下载次数
                    $downloadTotalNum++;
                }
                $tool->download_total_num += $downloadTotalNum;
                $tool->saveAndCheckResult();
            }
            // 2.日志
            LogMemberOpService::createToolLog($model, $tool);

            $transaction->commit();

            if ($model->download_type == 'other') {
                // 3.输出文件
                $this->createDownloadZip($model, $isDownloadWater);
            } else {// 返回下载视频地址
                return [
                    'download_url' => UploadService::getFileDownloadUrl(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_ATTACHMENT, $tool->file)
                ];
            }
            return ['id' => $tool->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 生成下载zip并输出
     * @param ToolForm $model
     * @param int $isDownloadWater 是否下载水印图【1是、0否】
     * @return void
     */
    private function createDownloadZip(ToolForm $model, int $isDownloadWater = 0)
    {
        if (empty($model->getDownloadToolFileList())) {
            return;
        }
        // 水印信息
        $toolWaterData = ToolWaterService::getProjectWaterData($model->getTool()->project_id);
        // 是否为水印文件
        $isWaterFile = $isDownloadWater && $toolWaterData['type'] ? true : false;
        if (count($model->getDownloadToolFileList()) === 1) {
            // 输出文件
            $file = $model->getDownloadToolFileList()[0]->file;
            if ($model->getDownloadToolFileList()[0]->type == ToolFile::TYPE_IMAGE) {
                $filePath = UploadService::getFileTruePath(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_IMAGE, $file);
                $filePath = self::getWaterImage($filePath, $file, $toolWaterData, $isDownloadWater);
            } else {
                $filePath = UploadService::getFileTruePath(SysFile::SITE_TOOL, SysFile::MODULE_TOOL_VIDEO, $file);
            }
            Yii::$app->response->sendFile($filePath, $file);
            // 删除水印文件
            $isWaterFile && @unlink($filePath);
            return;
        }

        // 创建临时目录
        $dir = Yii::getAlias('@attachment').'/tmp/tool_zip/';
        !is_dir($dir) && mkdir($dir, 0777, true);
        // 创建zip
        $zipName = "{$model->getTool()->name}.zip";
        $zipPath = $dir.$zipName;
        $zip = new \ZipArchive();
        $zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

        $imageNo = $videoNo = 0;
        $waterFile = [];// 水印图【临时图片】
        foreach ($model->getDownloadToolFileList() as $toolFile) {
            $ext = substr($toolFile->file, strripos($toolFile->file, '.'));
            if ($toolFile->type == ToolFile::TYPE_IMAGE) {
                $filePath = UploadService::getFileTruePath(SysFile::SITE_TOOL,SysFile::MODULE_TOOL_IMAGE, $toolFile->file);
                $filePath = self::getWaterImage($filePath, $toolFile->file, $toolWaterData, $isDownloadWater);
                $imageNo += 1;
                $zip->addFile($filePath, "image/{$imageNo}" . $ext);
                $isWaterFile && $waterFile[] = $filePath;
            } else {
                $filePath = UploadService::getFileTruePath(SysFile::SITE_TOOL,SysFile::MODULE_TOOL_VIDEO, $toolFile->file);
                $videoNo += 1;
                $zip->addFile($filePath, "video/{$videoNo}" . $ext);
            }
        }
        $zip->close();
        // 输出文件
        Yii::$app->response->sendFile($zipPath, $zipName);
        // 删除临时文件
        @unlink($zipPath);
        foreach ($waterFile as $file) {
            @unlink($file);
        }
    }

    /**
     * 获取真实下载图片【水印图or正常图】
     * @param string $filePath
     * @param string $fileName
     * @param array $toolWaterData
     * @param int $isDownloadWater
     * @return string
     * @throws \Exception
     */
    public static function getWaterImage(string $filePath, string $fileName, array $toolWaterData, int $isDownloadWater = 0): string
    {
        if ($isDownloadWater === 0 || $toolWaterData['type'] == 0) {
            return $filePath;
        }

        if ($toolWaterData['type'] == ToolWater::TYPE_TEXT) {
            $fontFile = Yii::getAlias('@root') . '/simkai.ttf';
            $filePath = FileHelper::createImgWaterByText($filePath, $fileName, $fontFile, $toolWaterData['text'], 14, 45, $toolWaterData['alpha']);
        } else {
//            Yii::getAlias('@attachment').'/water.png'
            $filePath = FileHelper::createImgWaterByImg($filePath, $fileName, $toolWaterData['file'], $toolWaterData['alpha']);
        }
        return $filePath;
    }
}
